package com.xiaomaoguai.spring.aop.cglib;

import com.xiaomaoguai.spring.aop.jdk.Math;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;
import java.util.Random;

/**
 * 采用cglib实现的动态代理,使用cglib可以实现动态代理，即使被代理的类没有实现接口，但被代理的类必须不是final类。
 *
 * @fileName: DynamicProxy.java
 * @author: WeiHui.Zhang
 * @date: 2016-11-10  10:58
 * @version: v1.0.0
 */
public class DynamicProxy implements MethodInterceptor {

	//被代理的对象
	Object targetObject;

	//动态生成一个新的类，使用父类的无参构造方法创建一个指定了特定回调的代理实例
	public Object getProxyObject(Object object) {
		this.targetObject = object;
		//增强器,动态代码生成器
		Enhancer enhancer = new Enhancer();
		//回调方法
		enhancer.setCallback(this);
		//设置生成类的父类类型
		enhancer.setSuperclass(targetObject.getClass());
		//动态生成字节码并返回代理对象
		return enhancer.create();
	}

	/**
	 * 拦截方法
	 *
	 * @param o
	 * @param method
	 * @param objects
	 * @param methodProxy
	 * @return
	 * @throws Throwable
	 */
	@Override
	public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
		// 被织入的横切内容，开始时间 before
		long start = System.currentTimeMillis();
		lazy();

		// 调用方法
		Object result = methodProxy.invoke(targetObject, objects);

		// 被织入的横切内容，结束时间
		Long span = System.currentTimeMillis() - start;
		System.out.println("共用时：" + span);
		return result;
	}

	// 模拟延时
	public void lazy() {
		try {
			int n = new Random().nextInt(500);
			Thread.sleep(n);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		Math math = (Math) new DynamicProxy().getProxyObject(new Math());
		int n1 = 100, n2 = 5;
		math.add(n1, n2);
		math.sub(n1, n2);
		math.mut(n1, n2);
		math.div(n1, n2);
	}
}
